/**
 * 
 */
package com.fclassroom.logger.service.common;

import java.util.List;
import java.util.Vector;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.aliyun.openservices.log.Client;
import com.aliyun.openservices.log.common.LogItem;
import com.aliyun.openservices.log.exception.LogException;
import com.aliyun.openservices.log.request.PutLogsRequest;
import com.fclassroom.ErrorCode.ModelType;
import com.fclassroom.ErrorCode.SystemModelType;
import com.fclassroom.logger.LoggerVar;
import com.fclassroom.logger.entity.LogCacheForSLS;
import com.jason.framework.util.DateUtil;
import com.jason.framework.util.SystemProperties;

/**
 * 通用方法类
 * 
 * @author zb
 * @Time 2017年5月17日 下午2:57:24
 */
@Service("methodService")
public class CommonMethodService implements ICommonMethodService {
	protected static final Logger logger = LogManager.getLogger();
	// 正则提取日志的类型，拆解出不同的来源和topic
	private String regex = "useend:([^(|+})]*)";
	@Autowired
	private LogCacheForSLS logCacheForSLS;
	private ExecutorService fixedThreadPool;
	/**
	 * 阿里云日志服务相关配置
	 */
	private Client slsClient;
	private Client slsSystemClient;
	// private String sls_family_student_logstore = "log_family_student";
	// private String sls_family_student_topic_web = "log_family_student_web";
	// private String sls_family_student_topic_app = "log_family_student_app";
	//
	// private String sls_family_parent_logstore = "log_family_parent";
	// private String sls_family_parent_topic_wx = "log_family_parent_wx";
	//
	// private String sls_teacher_logstore = "log_teacher";
	// private String sls_teacher_topic_web = "log_teacher_web";
	// private String sls_teacher_topic_pc = "log_teacher_pc";
	// private String sls_teacher_topic_app = "log_teacher_app";
	//
	// private String sls_report_logstore = "log_report";
	// private String sls_report_topic_web = "log_report_web";
	private final String STR_CALLBACK = "str_callback";// 标记位

	public CommonMethodService() {
		init();
	}

	private void init() {
		try {
			fixedThreadPool = Executors.newFixedThreadPool(3);// 线程池
			slsClient = new Client(LoggerVar.ALI_SLS_ENDPOINT, LoggerVar.ALI_SLS_ACCESSKEYID,
					LoggerVar.ALI_SLS_ACCESSKEYSECRET);
			slsSystemClient = new Client(LoggerVar.ALI_SLS_SYSTEM_ENDPOINT, LoggerVar.ALI_SLS_ACCESSKEYID,
					LoggerVar.ALI_SLS_ACCESSKEYSECRET);
			logger.info("阿里云日志服务启动成功");
		} catch (Exception e) {
			logger.error("阿里云日志服务启动失败，" + e.getMessage());
		}
	}

	/**
	 * 将日志信息放入指定队列中
	 * 
	 * @param msg
	 */
	@Override
	public void inputQueue(String msg) {
		if (StringUtils.isNotEmpty(msg)) {
			Pattern p = Pattern.compile(regex);
			Matcher m = p.matcher(msg);
			String topicStr = "";
			if (m.find()) {
				topicStr = m.group(1);
			} else {
				logger.error("Can not find topic:" + msg);
				return;
			}
			Integer topicIndex = Integer.parseInt(topicStr);
			// 11教师客户端；12教师安卓；13教师iOS；14和16教师web；15报表中心；
			// 21学生安卓；22学生iOS；23学生web；
			// 31家长微信
			switch (topicIndex) {
			case 11:
				logCacheForSLS.putTeacherPCLog(msg);
				break;
			case 12:
			case 13:
				logCacheForSLS.putTeacherAppLog(msg);
				break;
			case 14:
			case 16:
				logCacheForSLS.putTeacherWebLog(msg);
				break;
			case 15:
				logCacheForSLS.putReportWebLog(msg);
				break;
			case 21:
			case 22:
				logCacheForSLS.putStudentAppLog(msg);
				break;
			case 23:
				logCacheForSLS.putStudentWebLog(msg);
				break;
			case 31:
				logCacheForSLS.putParentWXLog(msg);
				break;
			default:
				break;
			}
		}
	}

	/**
	 * 用户数据直接上传到sls，不存储于队列
	 * 
	 * @param msg
	 */
	@Override
	public void dealAutoPostSLS(String msg) {
		try {
			fixedThreadPool.execute(new Runnable() {
				public void run() {
					if (StringUtils.isNotEmpty(msg)) {
						Pattern p = Pattern.compile(regex);
						Matcher m = p.matcher(msg);
						String topicStr = "";
						if (m.find()) {
							topicStr = m.group(1);
						} else {
							logger.error("Can not find topic:" + msg);
							return;
						}
						Integer topicIndex = Integer.parseInt(topicStr);
						// 11教师客户端；12教师安卓；13教师iOS；14和16教师web；15报表中心；
						// 21学生安卓；22学生iOS；23学生web；
						// 31家长微信
						switch (topicIndex) {
						case 11:
							autoPostSLS(msg, 11);
							break;
						case 12:
						case 13:
							autoPostSLS(msg, 12);
							break;
						case 14:
						case 16:
							autoPostSLS(msg, 16);
							break;
						case 15:
							autoPostSLS(msg, 15);
							break;
						case 21:
						case 22:
							autoPostSLS(msg, 21);
							break;
						case 23:
							autoPostSLS(msg, 23);
							break;
						case 31:
							autoPostSLS(msg, 31);
							break;
						default:
							logger.error("出现不匹配的数据：" + msg);
							break;
						}
					}
				}
			});
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public void dealSystemLog(String msg) {
		try {
			fixedThreadPool.execute(new Runnable() {
				public void run() {
					if (StringUtils.isNotEmpty(msg)) {
						Pattern p = Pattern.compile(regex);
						Matcher m = p.matcher(msg);
						String topicStr = "";
						if (m.find()) {
							topicStr = m.group(1);
						} else {
							logger.error("Can not find topic:" + msg);
							return;
						}
						Integer topicIndex = Integer.parseInt(topicStr);
						// 11教师客户端；12教师安卓；13教师iOS；14和16教师web；15报表中心；
						// 21学生安卓；22学生iOS；23学生web；
						// 31家长微信
						switch (topicIndex) {
						case 11:
							systemLogAutoPostSLS(msg, 11);
							break;
						case 12:
							systemLogAutoPostSLS(msg, 12);
							break;
						case 13:
							systemLogAutoPostSLS(msg, 12);// 暂时ios还没上线
							break;
						case 14:
							systemLogAutoPostSLS(msg, 14);
							break;
						case 16:
							systemLogAutoPostSLS(msg, 16);
							break;
						// 此系统日志不记录报表中心数据
						// case 15:
						// systemLogAutoPostSLS(msg, 15);
						// break;
						case 21:
							systemLogAutoPostSLS(msg, 21);
							break;
						case 22:
							systemLogAutoPostSLS(msg, 21);// 暂时ios还没上线
							break;
						case 23:
							systemLogAutoPostSLS(msg, 23);
							break;
						case 31:
							systemLogAutoPostSLS(msg, 31);
							break;
						default:
							logger.error("出现不匹配的数据：" + msg);
							break;
						}
					}
				}
			});
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("处理系统日志出错：" + e.getMessage());
		}
	}

	@Override
	public void autoPostSLS(String msg, Integer num) {
		if (StringUtils.isNotEmpty(msg)) {
			boolean callBackFlag = false;
			if (msg.substring(msg.length() - STR_CALLBACK.length()).contains(STR_CALLBACK)) {
				callBackFlag = true;
				msg = msg.replace(STR_CALLBACK, "");// 去掉重复上传标记，防止脏数据
			}
			Vector<LogItem> vector = new Vector<>();
			LogItem log5 = new LogItem();
			log5.PushBack(DateUtil.getNow(DateUtil.YYYY_MM_DD_HH_MM_SS), msg);
			vector.add(log5);
			try {
				PutLogsRequest logReq5 = new PutLogsRequest(LoggerVar.ALI_SLS_PROJECT, ModelType.getLogstoreValue(num),
						ModelType.getTopicValue(num), ModelType.getTopicValue(num), vector);
				slsClient.PutLogs(logReq5);
				// logger.info("成功上传数据，数据包大小：【{}】", vector.size());
			} catch (Exception e) {
				// 如果日志失败，应该考虑再次修正。
				handleException(e, msg, callBackFlag);
			}
			vector.clear();
		}

	}

	@Override
	public void systemLogAutoPostSLS(String msg, Integer num) {
		if (StringUtils.isNotEmpty(msg)) {
			boolean callBackFlag = false;
			if (msg.substring(msg.length() - STR_CALLBACK.length()).contains(STR_CALLBACK)) {
				callBackFlag = true;
				msg = msg.replace(STR_CALLBACK, "");// 去掉重复上传标记，防止脏数据
			}
			Vector<LogItem> vector = new Vector<>();
			LogItem log = new LogItem();
			log.PushBack(DateUtil.getNow(DateUtil.YYYY_MM_DD_HH_MM_SS), msg);
			vector.add(log);
			PutLogsRequest logReq = new PutLogsRequest(LoggerVar.ALI_SLS_SYSTEM_PROJECT,
					SystemModelType.getLogstoreValue(num), SystemModelType.getTopicValue(num),
					SystemModelType.getTopicValue(num), vector);
			try {
				slsSystemClient.PutLogs(logReq);
			} catch (Exception e) {
				handleSystemException(e, msg, callBackFlag);
			}
			logger.info("成功上传系统数据");
			vector.clear();
		}

	}

	/**
	 * 上传数据出错，重新上传（只重新上传一次，避免死循环）
	 * 
	 * @param e
	 * @param list
	 * @param callBackFlag
	 *            true:重新上传过,不再重新上传
	 */
	private void handleException(Exception e, String msg, boolean callBackFlag) {
		if (callBackFlag) {
			logger.error("出错数据已回滚一次，不再重新上传==msg:{},errmsg:{}", msg, e.getMessage());
		} else {
			msg = msg + STR_CALLBACK;// 添加标记位，重新上传时会去掉
			dealAutoPostSLS(msg);
			logger.error("上传数据出错=====msg:{},errmsg:{}", msg, e.getMessage());
		}
		e.printStackTrace();

	}

	/**
	 * 系统日志上传数据出错，重新上传（只重新上传一次，避免死循环）
	 * 
	 * @param e
	 * @param list
	 * @param callBackFlag
	 *            true:重新上传过,不再重新上传
	 */
	private void handleSystemException(Exception e, String msg, boolean callBackFlag) {
		if (callBackFlag) {
			logger.error("出错数据已回滚一次，不再重新上传==msg:{},errmsg:{}", msg, e.getMessage());
		} else {
			msg = msg + STR_CALLBACK;// 添加标记位，重新上传时会去掉
			dealSystemLog(msg);
			logger.error("上传system日志数据出错=====msg:{},errmsg:{}", msg, e.getMessage());
		}
		e.printStackTrace();

	}

}
